package com.jreque.queue;

import java.util.*;
import com.jreque.persistance.*;
import java.lang.*;

/**
 * Manages the queue of tasks. Takes care of adding, retrieving for execution, completion and restarting not finished tasks.
 */
public final class QueueManager {
    private static final int DEFAULT_TIMEOUT = 1000;
    
    /**
     */
    private IQueuePersistance persistance;

    /**
     * @param persistance 
     */
    public QueueManager(IQueuePersistance persistance) {
        if(persistance == null) throw new IllegalArgumentException("No queue persistance specified");
        this.persistance = persistance;
    }

    /**
     * Enqueues new task to queue.
     * @param task Task object to enueue.
     * @return Task ID if task was successfuly  enqueued.
     */
    public synchronized int enqueueTask(Task task) {
        return persistance.enqueueTask(task);
    }

    /**
     * Dequeues task from specified queue.
     * @param queueName Queue name to search task for.
     * @param timeout Maximum time in miliseconds to wait for task to execute.
     * @return Dequeued task object to execute.
     */
    public synchronized Task dequeueTask(String queueName, int timeout) {
        return persistance.dequeueTask(queueName, timeout);
    }

    /**
     * Marks specified task as completed.
     * @param task Task to mark as executed and completed.
     */
    public synchronized void completeTask(Task task) {
        persistance.completeTask(task);
    }

    /**
     * Deletes task from queue. Fails if task was finished or not enqueued. If task was dequeued it will continue execution but will not requeue in case of errors.
     * @param taskID ID of task to delete
     * @return Indicates if task was deleted successfully
     */
    public synchronized boolean deleteTask(int taskID) {
        return persistance.deleteTask(taskID);
    }

    /**
     * Gets settings for specified queue or global.
     * @param queueName Name of queue to get settings for. Use Null get global settings.
     * @return Map with all settings set.
     */
    public HashMap getSettings(String queueName) {
        return persistance.getSettings(queueName);
    }

    /**
     * Sets new setting value for specified queue or global setting.
     * @param setting Setting key name.
     * @param value New setting value.
     * @param queueName Name of queue to set settings for. Use Null for global settings.
     * @return Old setting value. Null if t wasn't set before.
     */
    public synchronized String addSetting(String queueName, String setting, String value) {
        return persistance.addSetting(queueName, setting, value);
    }

    /**
     * Retrieves global stats or for specified queue.
     * @param queueName Name of queue to query stats for. Use Null to retrieve global stats.
     * @return Map with stats values.
     */
    public HashMap getStats(String queueName) {
        return persistance.getStats(queueName);
    }
    
    /**
     * Retrieves timeout setting for specified queue
     * @param queueName Name of the queue to retrieve the setting for
     * @return timeout in miliseconds
     */
    public int getTimeout(String queueName) {
        int timeout = DEFAULT_TIMEOUT;
        try {
            String timeoutStr = persistance.getSetting(queueName, "timeout");
            if(timeoutStr != null) timeout = Integer.parseInt(timeoutStr);
        } catch (NumberFormatException e) {}
        return timeout;
    }
}

